gRPC入门(Golang)保姆级教程 您所在的位置:网站首页 golang 服务端Java客户端 gRPC入门(Golang)保姆级教程

gRPC入门(Golang)保姆级教程

2024-05-28 19:20| 来源: 网络整理| 查看: 265

gRPC入门(Golang) gRPC入门RPC简介gRPC简介gRPC特点概览为什么要用gRPC 安装gRPC安装Protocol Buffers v3安装Protoc Plugin安装检查gRPC入门示例开发步骤项目结构编写proto代码编写Server端Go代码编写Client端Go代码运行结果 Protobuf命令学习-I (-proto_path)--go_out指定源文件指定gprc选项,生成grpc功能--go_opt完整编译

gRPC入门 RPC简介

RPC == Remote Procedure Call == 远程过程调用

允许运行于一台计算机的程序调用另一台计算机的子程序。

调用包含了传输协议和编码(对象序列号)协议等等。

gRPC简介

gRPC是一个高性能、开源、通用的RPC框架,基于HTTP2协议标准设计开发,默认采用 Protocol Buffers 数据序列化协议。

Protocol Buffers 是一种与语言、平台无关,可扩展的序列化结构化数据的方法,常用于通信协议,数据存储等等。相较于 JSON、XML,它更小、更快、更简单,因此也更受开发人员的青眯

gRPC特点

1、HTTP/2

2、Protobuf

3、客户端、服务端基于同一份 IDL

IDL是Interface description language的缩写,指接口描述语言

4、移动网络的良好支持

5、支持多语言

概览

gRPC简介 - 图1

讲解

1、客户端(gRPC Sub)调用 A 方法,发起 RPC 调用

2、对请求信息使用 Protobuf 进行对象序列化压缩(IDL)

3、服务端(gRPC Server)接收到请求后,解码请求体,进行业务逻辑处理并返回

4、对响应结果使用 Protobuf 进行对象序列化压缩(IDL)

5、客户端接受到服务端响应,解码请求体。回调被调用的 A 方法,唤醒正在等待响应(阻塞)的客户端调用并返回响应结果

为什么要用gRPC

使用gRPC, 我们可以一次性的在一个.proto文件中定义服务并使用任何支持它的语言去实现客户端和服务端,反过来,它们可以应用在各种场景中,从Google的服务器到你自己的平板电脑—— gRPC帮你解决了不同语言及环境间通信的复杂性。使用protocol buffers还能获得其他好处,包括高效的序列号,简单的IDL以及容易进行接口更新。总之一句话,使用gRPC能让我们更容易编写跨语言的分布式代码。

安装gRPC go get -u google.golang.org/grpc

在这里插入图片描述

安装Protocol Buffers v3

安装用于生成gRPC服务代码的协议编译器

下载地址:https://github.com/google/protobuf/releases

在这里插入图片描述

在这里插入图片描述

bin 目录下的 protoc 是可执行文件。include 目录下的是 google 定义的.proto文件,我们import "google/protobuf/timestamp.proto"就是从此处导入。

我们需要将下载得到的可执行文件protoc所在的 bin 目录加到我们电脑的环境变量中。

安装Protoc Plugin

编译器插件

我们是使用Go语言做开发,接下来执行下面的命令安装protoc的Go插件:

Golang return &pb.HelloResponse{Replay: "Hello " + in.Name}, nil } func main() { // 监听本地的8972端口 lis, err := net.Listen("tcp", ":8972") if err != nil { fmt.Printf("failed to listen: %v", err) return } s := grpc.NewServer() // 创建gRPC服务器 pb.RegisterGreeterServer(s, &server{}) // 在gRPC服务端注册服务 // 启动服务 err = s.Serve(lis) if err != nil { fmt.Printf("failed to serve: %v", err) return } } 创建 gRPC Server 对象,你可以理解为它是 Server 端的抽象对象将 server(其包含需要被调用的服务端接口)注册到 gRPC Server 的内部注册中心。这样可以在接受到请求时,通过内部的服务发现,发现该服务端接口并转接进行逻辑处理创建 Listen,监听 TCP 端口gRPC Server 开始 lis.Accept,直到 Stop 或 GracefulStop

编译并执行 hello_server:

go build hello_server.exe 编写Client端Go代码

步骤和Server端相同。

在 go_grpc_example 文件夹下再新建一个 hello_client 文件夹,新建一个空白的 main.go, 在项目根目录下执行 go mod init hello_client

然后再新建一个 pb 文件夹,把上面写的 proto 代码保存到 hello.proto,放入pb文件夹内。

此时,项目目录结构为:

go_grpc_example/hello_client ├── go.mod ├── go.sum ├── main.go └── pb └── hello.proto

然后把 hello.proto 文件中的 go_package 修改,如下:

option go_package = "hello_client/pb;pb";

然后在 pb 目录下执行以下命令,根据 hello.proto 生成go源码文件

protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative hello.proto

生成后的go源码文件会保存在 pb 文件夹下,如下:。

go_grpc_example/hello_client ├── go.mod ├── go.sum ├── main.go └── pb ├── hello.pb.go ├── hello.proto └── hello_grpc.pb.go

把下面的内容添加到 hello_client/main.go 中。调用 http_server 提供的 SayHello RPC服务。

package main import ( "context" "flag" "log" "time" "hello_client/pb" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" ) // hello_client const ( defaultName = "world" ) var ( addr = flag.String("addr", "127.0.0.1:8972", "the address to connect to") name = flag.String("name", defaultName, "Name to greet") ) func main() { flag.Parse() // 连接到server端,此处禁用安全传输 conn, err := grpc.Dial(*addr, grpc.WithTransportCredentials(insecure.NewCredentials())) if err != nil { log.Fatalf("did not connect: %v", err) } defer conn.Close() c := pb.NewGreeterClient(conn) // 执行RPC调用并打印收到的响应数据 ctx, cancel := context.WithTimeout(context.Background(), time.Second) defer cancel() r, err := c.SayHello(ctx, &pb.HelloRequest{Name: *name}) if err != nil { log.Fatalf("could not greet: %v", err) } log.Printf("Greeting: %s", r.GetReplay()) } 创建与给定目标(服务端)的连接交互创建 server的客户端对象发送 RPC 请求,等待同步响应,得到回调后返回响应结果输出响应结果

保存后将http_client编译并执行:

go build hello_client.exe -name=ersan 运行结果

得到如下结果,说明RPC调用正确:

在这里插入图片描述

Protobuf命令学习 -I (-proto_path) protoc --proto_path=proto --go_out=. proto/hello.proto --proto_path` 可以简写为`-I` ,表示读取`*.proto文件的目录 –go_out protoc --go_out=. hello.proto // 不使用-I,直接进入proto的文件夹执行

--go_out 参数是用来指定 protoc-gen-go 插件的工作方式和Go代码的生成位置

--go_out` 表示将`*.proto文件`转换为`golang语言 = 前半部分是用转换成哪个语言,go_out表示转换为go语言。 = 后半部分,表示的是转换生成后的pb.go文件,放在哪个文件夹下。 . 或者 :. 都表示将生成的pb.go文件放入当前的目录下。

使用–go_out把proto文件转为golang语言时,因为protobuf的源码服务中没有对go语言的支持,所以我们需要proto-gen-go插件( 该插件会根据.proto文件生成一个后缀为.pb.go的文件,包含所有.proto文件中定义的类型及其序列化方法。)来生成go代码。

–go_out的写法常见的比如: --go_out=paths=import:. 、 --go_out=paths=source_relative:.,或者 --go_out=plugins=grpc:.

从这里可以看出 --go_out 主要的两个参数是 plugins 和 paths ,分别表示生成Go代码所使用的插件,以及生成的Go代码的位置。

paths 参数有两个选项,分别是 import 和 source_relative,默认为 import,表示按照生成的Go代码的包的全路径去创建目录层级,source_relative 表示按照 proto源文件的目录层级去创建Go代码的目录层级,如果目录已存在则不用创建。

plugins :指定依赖的插件

指定源文件 protoc --go_out=:. ./hello.proto protoc --go_out=:. hello.proto

上面两个等价,都是读取当前目录下的hello.proto文件。我们用 hello.proto 文件作为执行源头文件。

指定gprc选项,生成grpc功能

我们一般如果是go语言的话,用proto都是结合grpc来用的。

protoc --go_out=plugins=grpc:. hello.proto

它表示用grpc服务生成 pb.go 文件。它执行的时候,会检查是否已经下载grpc库( google.golang.org/grpc )。

要想使用grpc功能,那么proto文件里得定义rpc相关的服务,这样生成的pb.go文件,才会生成相关rpc数据

注意这里的 :. 就和之前不同了,因为之前没有生成grpc插件,所以 :. = . ,现在需要使用grpc插件,那么这里的 : 就是一个分隔符。分割成两部分:

--go_out === plugins的类型 : 输出的路径

单独使用这里的proto命令会报错 “plugins are not supported” ,下面会讲到

–go_opt

–go_opt表示生成go文件时候的目录选项

–go_opt=paths=source_relative 表示 生成的文件与proto在同一目录

完整编译

在 .proto 文件的目录下,使用如下命令编译:

protoc --go_out=. --go-grpc_out=. ./hello.proto

它使用到了我们在上面安装的两个插件,它会生成两个文件,分别是 .pb.go 和 _grpc.pb.go 两个文件,前者主要是对 message 生成对应的结构体和方法,后者生成 gRPC ,主要是对 service 生成对应的 interface 和方法

另外,还有一个 --go_opt=paths=source_relative 命令,其含义代表生成的 .pb.go 文件路径不依赖于 .proto 文件中的 option go_package 配置项,直接在 go_out 指定的目录下生成 .pb.go 文件( .pb.go 文件的package名还是由 option go_package 决定)

--go-grpc_opt=paths=source_relative ,针对 _grpc.pb.go 文件,作用同上。

之前我们提到一个 “plugins are not supported” 问题,当前版本编译时,之前的方法 protoc --go_out=plugins=grpc:. *.proto 不再使用,转而用 protoc --go_out=. --go-grpc_out=. ./hello.proto 代替。

github的方式,需要使用--go_out=plugins=grpc 来去进行生成,而在golang.org方式中,弃用了这种方式,使用protoc-gen-go将不在支持gRPC service的定义,需要使用新的插件protoc-gen-go-grpc。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有